/*
 * Core TFX file. Works together with api.js.
 * 
 * This is run on the page scope, and provides a frontend Widget
 * class for the Web Worker sandboxed widgets.
 */
(function() {
	if (!window.tfx) {
		window.tfx = {
			ROOT_URL : 'https://thermetics-fx.appspot.com/',
			STYLES_URL : 'https://thermetics-fx.appspot.com/static/styles/',
			SCRIPT_URL : 'https://thermetics-fx.appspot.com/static/scripts/',
			WIDGET_URL : 'https://thermetics-fx.appspot.com/app/widgets/',
			APP_URL : 'https://thermetics-fx.appspot.com/app/',
			API_URL: 'https://thermetics-fx.appspot.com/app/api/'
		}
	}
	
	tfx.API_VERSION = '0';
	tfx.APP_VERSION = '0.0.4';
	tfx.ready = function(callback) {
		if (callback) {
			tfx._readyCallback = callback;
		}
		else {
			tfx._readyCallback();
		}
	};
	
	function Widget(name, url) {
		var widgetName = name;
		var widgetFrame = null;
		var widgetLoaded = false;
		var readyCallback = null;
		
		if (!url) {
			url = tfx.WIDGET_URL + name;
		}
		
		//Public members of this class.
		var PUBLIC = {
			//Load the widget.
			load: function(asCore) {
				if (!widgetLoaded) {
					widgetLoaded = true;
					
					widgetFrame = $('<iframe></iframe>');
					widgetFrame.attr('src', url);
					widgetFrame.css('display', 'none');
					widgetFrame.attr('id', 'tfx_widget_' + name);
					
					widgetFrame.load(function() {
						var environment = {
							widgetName: name,
							appVersion: tfx.APP_VERSION,
							apiVersion: tfx.API_VERSION,
							APP_URL: tfx.APP_URL,
							API_URL: tfx.API_URL,
							SCRIPT_URL: tfx.SCRIPT_URL,
							WIDGET_URL: tfx.WIDGET_URL,
							STYLES_URL: tfx.STYLES_URL
						};
						
						if (asCore) {
							environment.CORE = true;
						}
						
						//Initially, this widget can operate on itself.
						widgetFrame.wormhole({
							payload: environment,
							selectors: [ '#tfx_widget_' + name ],
							methods: [ 'css', 'hide', 'show', 'toggle', '~click', '~mouseleave' ],
							proxy: PUBLIC
						});
						
						//Trust handshake
						$.pm({
							target: widgetFrame[0].contentWindow,
							type: 'handshake',
							data: { state: 'needUUID' },
							error: function(err) { 
								alert('Trust Handshake failed from parent end (State = needUUID)\n' + err.message); 
							}
						});
					});
					
					$('body').append(widgetFrame);
				}
			},
			
			widgetName: function() {
				return name;
			},
			
			exposeSelector: function(selector) {
				widgetFrame.wormhole({ selectors: [ selector ] });
			},
			
			//Callback fired when the widget loads.
			ready: function(callback) {
				readyCallback = callback;
			},
			
			//Send a message to the widget.
			postMessage: function(message, data) {
				var payload = {
					message: message,
					data: data
				};
	
				$.pm({
					target: widgetFrame[0].contentWindow, //[0] is the DOM element.
					type: 'message',
					data: payload,
					error: function(err) {
						alert('postMessage error: ' + err.message);
					},
					success: function() {
						
					}
				});
			}
		};
		
		return PUBLIC;
	}
	
	/* Load TFX dependencies */
	if (window) {
		$.getScript(tfx.SCRIPT_URL + 'jq-plugins/jquery.synchronize.js', function() {
			$.synchronize([
			 	$.callLater($.getScript, tfx.SCRIPT_URL + 'api.js'),
			 	$.callLater($.getScript, tfx.SCRIPT_URL + 'jq-plugins/jquery.postmessage.js'),
			 	$.callLater($.getScript, tfx.SCRIPT_URL + 'jq-plugins/jquery.form.js'),
			 	$.callLater($.getScript, tfx.SCRIPT_URL + 'jq-plugins/jquery.wormhole-parent.js'),
			 	$.callLater(finishLoad)
		 	]);
			
			function finishLoad() {
				//Load core UI CSS File
				Page.addCssFile(tfx.STYLES_URL + 'ui.css');
				
				//Allow wormhole access to all TFX APIs.
				$.exposeAll(Core);
				$.exposeAll(Thread);
				$.exposeAll(Page);
				$.exposeAll(__wwBridge);
				$.exposeAll(__wwBridge.Cloud);
				$.exposeAll(__wwBridge.UI);
				
				//Listen for hosted iframe postMessage events.
				$.pm.bind('tfxHostedRequest', function(req) {
					var widgetName = req.widget;
					var message = req.message;
					var payload = req.data;
					
					if (window.widgets[widgetName]) {
						window.widgets[widgetName].postMessage(message, payload);
					}
				});
				
				//Listen for widget handshake events.
				var trustedUUIDs = {}; //uuid -> iframe map
				$.pm.bind('handshake', function(handshake) {
					if (handshake.state == 'uuid') {
						trustedUUIDs[handshake.uuid] = this;
						$.pm({
							target: this, //widget frame that sent the request
							type: 'handshake',
							data: { state: 'gotUUID' },
							error: function(err) { 
								alert('Trust Handshake failed from parent end (State = gotUUID)\n' + err.message);
							}
						});					
					}
				});
				
				//Listen for trusted module requests.
				$.pm.bind('tfxTrustedModuleHandshake', function(handshake) {
					var uuid = handshake.uuid;
					var widgetFrame = trustedUUIDs[uuid];
					
					if (widgetFrame) {
						if (handshake.state == 'verify') {
							//widget is asking us to verify its identity.
							//by getting to this part it's been verified already.
							$.pm({
								target: widgetFrame,
								type: 'tfxTrustedModuleHandshake',
								data: { state: 'verified', moduleName: handshake.moduleName },
								error: function() { alert('Trusted Module verification failed from parent end'); }
							});
						}
						
						if (handshake.state == 'run') {
							$.getScript(handshake.moduleScript);
						}
					}
					else {
						//this request did not come from an authorized widget!!
					}
				});
				
				//Initialize widgets. Dashboard is always loaded as it contains core stuff.
				window.widgets = {};
				window.widgets['dashboard'] = new Widget('dashboard');
				window.widgets.dashboard.load(true);
				
				//Hardcoded widgets for testing.
				window.widgets['reports'] = new Widget('reports');
				window.widgets.reports.load();
							
				if (tfx._readyCallback) {
					tfx.ready();
				}
			}
		});
	}
})();